Next.jsでCloudscape Design Systemを試してみた
しばたです。
前の記事でNext.jsを試す環境を作ったので本記事ではCloudscapeを実際に試してみます。
Cloudscape Design Systemとは?
Cloudscape Design SystemはAWSが作成しオープンソースで公開しているWEBデザインシステムです。
もともとAWSが内部向けに作成し改善していたものが今年の7月に一般公開されました。
雑に言ってしまえば「マネジメントコンソール風のUIをつくれるやつ」なんですが、デザインシステムの名の通りUIコンポーネント以外にデザインパターンやデモも公開されています。
注意事項
本記事ではこちらの手順に従い最初の一歩を試してみようと思っていました。
ただ、手順をよく読んでみると最後の最後に、
Bundling with Next.js (optional)
There are known limitations when using Cloudscape with the React Framework Next.js . To follow the discussion, see the corresponding issue on GitHub .
という事でNext.jsでの利用には制限がある旨が記載されていました...
具体的な話はGitHub Discussionsで議論されています。
現時点ではNext.jsでCloudscapeを利用する際にnext-transpile-modules
によるトランスパイルが必要なのと、警告ログが出るなどの不都合があるそうです。
試してみた
という事で実環境での利用はちょっと難しそう[1]ですが、まあ、やるだけやってみます。
検証環境
検証環境は前回の記事で作成したNode.js 18.12.0 on WSL2(Ubuntu 20.04)をそのまま使います。
Next.jsアプリケーションの用意
まずはベースとなるアプリケーションの雛形を用意します。
~/src/
ディレクトリでcloudscape-sample
という名前のアプリケーションを作成します。
# ディレクトリ移動
cd ~/src/
# Next.jsアプリケーション cloudscape-sample を作成
npx create-next-app@latest cloudscape-sample --use-npm --ts
なんとなくTypeScriptアプリケーションにしてみました。
Reactコンポーネントのインストール
チュートリアルとは違い新規アプリケーションを作るだけなのでエラーにはならないはずです。
作成されたcloudscape-sample
ディレクトリに移動し、
@cloudscape-design/global-styles
@cloudscape-design/components
の2種のコンポーネントをインストールしてやります。
また、先述の通りNext.jsの場合はトランスパイルが必要なため
next-transpile-modules
next-compose-plugins
の2つのコンポーネントもインストールしてやります。
こちらは開発用のため--save-dev
(-D
)パラメーター付きでインストールします。
# アプリケーションディレクトリへ移動
cd ./cloudscape-sample
# Reactコンポーネントをインストール
npm install @cloudscape-design/global-styles
npm install @cloudscape-design/components
# トランスパイル関連のモジュールは --save-dev インストール
npm install -D next-transpile-modules next-compose-plugins
エラー無くインストールできればOKです。
今回は@cloudscape-design/components
のインストール時にいくつか依存関係周りの警告が出たのとd3-color
が脆弱性のあるバージョンである旨の警告がでましたが、現状打つ手が無い脆弱性だったので無視して続行することにします...
# @cloudscape-design/componentsインストール時に警告が出る
$ npm install @cloudscape-design/components
npm WARN ERESOLVE overriding peer dependency
npm WARN ERESOLVE overriding peer dependency
npm WARN ERESOLVE overriding peer dependency
added 37 packages, and audited 276 packages in 11s
80 packages are looking for funding
run `npm fund` for details
4 high severity vulnerabilities
Some issues need review, and may require choosing
a different dependency.
Run `npm audit` for details.
# また、d3-color Ver.3.1.0の脆弱性が出ているがVer.3.1.0が最新バージョンのためどうすることもできない...
$ npm audit
# npm audit report
d3-color <3.1.0
Severity: high
d3-color vulnerable to ReDoS - https://github.com/advisories/GHSA-36jr-mh4h-2g58
No fix available
node_modules/d3-color
d3-interpolate 0.1.3 - 2.0.1
Depends on vulnerable versions of d3-color
node_modules/d3-interpolate
d3-scale 0.1.5 - 3.3.0
Depends on vulnerable versions of d3-interpolate
node_modules/d3-scale
@cloudscape-design/components *
Depends on vulnerable versions of d3-scale
node_modules/@cloudscape-design/components
4 high severity vulnerabilities
Some issues need review, and may require choosing
a different dependency.
next.config.jsの書き換え
次にNext.jsの場合はトランスパイルのためにnext.config.js
の内容を変更してやる必要があります。
next.config.js
の内容を以下の様に変えておきます。
// TypeScriptの場合
const withTM = require('next-transpile-modules')(['@cloudscape-design/components']);
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
swcMinify: true,
}
const buildConfig = _phase => {
const plugins = [withTM]
const config = plugins.reduce((acc, next) => next(acc), {
...nextConfig
})
return config
}
module.exports = buildConfig();
ちなみにJavaScriptの場合は以下の様にするそうです。
// JavaScriptの場合
const withTranspileModules = require('next-transpile-modules')
const withPlugins = require('next-compose-plugins')
const nextConfig = {
reactStrictMode: true,
swcMinify: true,
}
// Here we will add a plugin to our configuration to transpile the CloudScape components into
module.exports = withPlugins([withTranspileModules(['@cloudscape-design/components'])], nextConfig)
アプリケーションの記述
あとはアプリケーションコードをよしなに書いてやります。
今回は元の手順通りにpages/index.tsx
の内容を以下の様に変えてみます。
import { useState } from "react";
import Header from "@cloudscape-design/components/header";
import Container from "@cloudscape-design/components/container";
import SpaceBetween from "@cloudscape-design/components/space-between";
import Input from "@cloudscape-design/components/input";
import Button from "@cloudscape-design/components/button";
export default function App() {
const [value, setValue] = useState("");
return (
<SpaceBetween size="m">
<Header variant="h1">Hello World!</Header>
<Container>
<SpaceBetween size="s">
<span>Start editing to see some magic happen</span>
<Input
value={value}
onChange={(event) => setValue(event.detail.value)}
/>
<Button variant="primary">Click me</Button>
</SpaceBetween>
</Container>
</SpaceBetween>
);
}
また、デフォルトで作成された使わないファイル群を削除しておきます。
pages/_app.tsx
pages/api/
ディレクトリstyles/globals.css
styles/Home.module.css
この状態でnpm run dev
コマンドを実行し開発サーバーを動作させてみるとこんな感じで各コンポーネントが表示されます。
見かけ上は良い感じに見えますが、コンソール上では以下の様なuseLayoutEffect
に関する警告ログが出ています。
Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server renderer's output format. This will lead to a mismatch between the initial, non-hydrated UI and the intended UI. To avoid this, useLayoutEffect should only be used in components that render exclusively on the client. See https://reactjs.org/link/uselayouteffect-ssr for common fixes.
GitHub Discussionsの議論を見る限り無害な警告らしいですがあまり良い気はしないですね。
一応_app.tsx
に以下の記述を追加して無理やり警告を非表示にすることは出来る様です。
import React from 'react'
if (typeof window === 'undefined') React.useLayoutEffect = () => {}
記述例
import type { AppProps } from 'next/app'
import React from 'react'
if (typeof window === 'undefined') React.useLayoutEffect = () => {}
export default function App({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />
}
その他コンポーネントとデモ
ここまでの手順で最低限の動作確認ができました。
その他のコンポーネントに関しては以下のドキュメントに詳細が記載されています。
各コンポーネントに対してPlaygroundでのサンプルコードが確認できたりかなり充実した内容になっています。
加えて多くのデモがソースコード付きで公開されています。
あとはこれらをお手本にして試行錯誤すれば望み通りのサイトが作れる...はずです。多分...
最後に
簡単ですが以上となります。
とりあえず基本的なところまでは実現できましたが、これを応用し望みのレイアウトを実現するまではもうしばらくの時間がかかりそうです。
少なくともNext.js初心者の私には厳しい... ↩︎